namespace SimpleWebServices.Web.UI.Html.Validation
{
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Diagnostics.CodeAnalysis;
    using SimpleWebServices.Data;
    using SimpleWebServices.Web.UI.Html.Elements;

    public abstract class Validator : IValidate
    {
        protected Validator()
            : this(null)
        {
        }

        protected Validator(IInnerElements display)
        {
            this.Display = display;
            this.Errors = new List<IError>();
            this.ErrorText = "The information is not valid.";
        }

        public IInnerElements Display
        {
            get;
            set;
        }

        public IList<IError> Errors
        {
            get;
            private set;
        }

        public string ErrorText
        {
            get;
            set;
        }

        public virtual void Configure(IElement element, DataCollection data)
        {
            if (null != data)
            {
                foreach (var datum in data)
                {
                    if ("Display".Equals(datum.Key, StringComparison.OrdinalIgnoreCase))
                    {
                        this.SetDisplay(element, datum.Value);
                    }
                    else if ("ErrorText".Equals(datum.Key, StringComparison.OrdinalIgnoreCase))
                    {
                        this.ErrorText = datum.Value;
                    }
                }
            }
        }

        public void DisplayErrors()
        {
            if (0 != this.Errors.Count)
            {
                TextString error = new TextString(this.Errors[0].Description);
                this.Display.Elements.Clear();
                this.Display.Elements.Add(error);
                this.Display.Class = "error";
            }
        }

        public abstract bool Validate(IElement element);

        protected void SetDisplay(IElement element, Name display)
        {
            if (null == element)
            {
                throw new ArgumentNullException("element");
            }

            this.SetDisplay(element as IInnerElements, display);
        }

        protected void SetDisplay(IInnerElements element, Name display)
        {
            if (null == element)
            {
                throw new ArgumentNullException("element");
            }

            try
            {
                this.SetDisplayElement(element[display] as IInnerElements);
            }
            catch (KeyNotFoundException exception)
            {
                throw new ConfigurationErrorsException("The display element was not found.", exception);
            }
        }

        private void SetDisplayElement(IInnerElements display)
        {
            if (null == display)
            {
                throw new ConfigurationErrorsException("The display element must implement IInnerHtml.");
            }

            this.Display = display;
        }
    }
}